{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 11.3 Date Ranges, Frequencies, and Shifting（日期范围，频度，和位移）\n",
    "\n",
    "普通的时间序列通常是不规律的，但我们希望能有一个固定的频度，比如每天，每月，或没15分钟，即使有一些缺失值也没关系。幸运的是，pandas中有一套方法和工具来进行重采样，推断频度，并生成固定频度的日期范围。例如，我们可以把样本时间序列变为固定按日的频度，需要调用resample："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2011-01-02    2.005739\n",
       "2011-01-05   -0.265967\n",
       "2011-01-07   -0.353966\n",
       "2011-01-08   -0.646626\n",
       "2011-01-10    1.599440\n",
       "2011-01-12   -0.407854\n",
       "dtype: float64"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from datetime import datetime\n",
    "\n",
    "\n",
    "dates = [datetime(2011, 1, 2), datetime(2011, 1, 5),\n",
    "         datetime(2011, 1, 7), datetime(2011, 1, 8), \n",
    "         datetime(2011, 1, 10), datetime(2011, 1, 12)]\n",
    "\n",
    "ts = pd.Series(np.random.randn(6), index=dates)\n",
    "ts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "resampler = ts.resample('D')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里的'D'表示按日的频度（daily frequency）。\n",
    "\n",
    "关于频度（frequency）和重采样（resampling）的转换，会在11.6进行具体介绍，这里我们展示一些基本的用法。\n",
    "\n",
    "# 1 Generating Date Ranges（生成日期范围）\n",
    "\n",
    "之前虽然用过，但没有做解释，其实pandas.date_range是用来生成DatetimeIndex的，使用时要根据频度来指明长度："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',\n",
       "               '2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',\n",
       "               '2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',\n",
       "               '2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',\n",
       "               '2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20',\n",
       "               '2012-04-21', '2012-04-22', '2012-04-23', '2012-04-24',\n",
       "               '2012-04-25', '2012-04-26', '2012-04-27', '2012-04-28',\n",
       "               '2012-04-29', '2012-04-30', '2012-05-01', '2012-05-02',\n",
       "               '2012-05-03', '2012-05-04', '2012-05-05', '2012-05-06',\n",
       "               '2012-05-07', '2012-05-08', '2012-05-09', '2012-05-10',\n",
       "               '2012-05-11', '2012-05-12', '2012-05-13', '2012-05-14',\n",
       "               '2012-05-15', '2012-05-16', '2012-05-17', '2012-05-18',\n",
       "               '2012-05-19', '2012-05-20', '2012-05-21', '2012-05-22',\n",
       "               '2012-05-23', '2012-05-24', '2012-05-25', '2012-05-26',\n",
       "               '2012-05-27', '2012-05-28', '2012-05-29', '2012-05-30',\n",
       "               '2012-05-31', '2012-06-01'],\n",
       "              dtype='datetime64[ns]', freq='D')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "index = pd.date_range('2012-04-01', '2012-06-01')\n",
    "index"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "默认，date_range会生成按日频度的时间戳。如果我们只传入一个开始或一个结束时间，还必须传入一个数字来表示时期："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',\n",
       "               '2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',\n",
       "               '2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',\n",
       "               '2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',\n",
       "               '2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20'],\n",
       "              dtype='datetime64[ns]', freq='D')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.date_range(start='2012-04-01', periods=20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2012-05-13', '2012-05-14', '2012-05-15', '2012-05-16',\n",
       "               '2012-05-17', '2012-05-18', '2012-05-19', '2012-05-20',\n",
       "               '2012-05-21', '2012-05-22', '2012-05-23', '2012-05-24',\n",
       "               '2012-05-25', '2012-05-26', '2012-05-27', '2012-05-28',\n",
       "               '2012-05-29', '2012-05-30', '2012-05-31', '2012-06-01'],\n",
       "              dtype='datetime64[ns]', freq='D')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.date_range(end='2012-06-01', periods=20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "开始和结束的日期，严格指定了用于生成日期索引（date index）的边界。例如，如果我们希望日期索引包含每个月的最后一个工作日，我们要设定频度为'BM'(business end of month，每个月的最后一个工作日，更多频度可以看下面的表格)，而且只有在这个日期范围内的日期会被包含进去："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-28',\n",
       "               '2000-05-31', '2000-06-30', '2000-07-31', '2000-08-31',\n",
       "               '2000-09-29', '2000-10-31', '2000-11-30'],\n",
       "              dtype='datetime64[ns]', freq='BM')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.date_range('2000-01-01', '2000-12-01', freq='BM')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "时间序列频度：\n",
    "\n",
    "![](http://oydgk2hgw.bkt.clouddn.com/pydata-book/v4ae4.png)\n",
    "\n",
    "date_range会默认保留开始或结束的时间戳："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2012-05-02 12:56:31', '2012-05-03 12:56:31',\n",
       "               '2012-05-04 12:56:31', '2012-05-05 12:56:31',\n",
       "               '2012-05-06 12:56:31'],\n",
       "              dtype='datetime64[ns]', freq='D')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.date_range('2012-05-02 12:56:31', periods=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "有些时候我们的时间序列数据带有小时，分，秒这样的信息，但我们想要让这些时间戳全部归一化到午夜（normalized to midnight, 即晚上0点），这个时候要用到normalize选项："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2012-05-02', '2012-05-03', '2012-05-04', '2012-05-05',\n",
       "               '2012-05-06'],\n",
       "              dtype='datetime64[ns]', freq='D')"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nor_date = pd.date_range('2012-05-02 12:56:31', periods=5, normalize=True)\n",
    "nor_date"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2012-05-02 00:00:00', offset='D')"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nor_date[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到小时，分，秒全部变为0\n",
    "\n",
    "# 2 Frequencies and Date Offsets（频度和日期偏移）\n",
    "\n",
    "pandas中的频度由一个基本频度（base frequency）和一个乘法器（multiplier）组成。基本频度通常用一个字符串别名（string alias）来代表，比如'M'表示月，'H'表示小时。对每一个基本频度，还有一个被称之为日期偏移（date offset）的对象。例如，小时频度能用Hour类来表示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from pandas.tseries.offsets import Hour, Minute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Hour>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hour = Hour()\n",
    "hour"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过传入一个整数，我们可以定义一个乘以偏移的乘法（a multiple of an offset）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<4 * Hours>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "four_hours = Hour(4)\n",
    "four_hours"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在很多情况下，我们不需要创建这些对象，而是使用字符串别名，比如'H'或'4H'。在频度前加一个整数，就能作为一个乘法器："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 04:00:00',\n",
       "               '2000-01-01 08:00:00', '2000-01-01 12:00:00',\n",
       "               '2000-01-01 16:00:00', '2000-01-01 20:00:00',\n",
       "               '2000-01-02 00:00:00', '2000-01-02 04:00:00',\n",
       "               '2000-01-02 08:00:00', '2000-01-02 12:00:00',\n",
       "               '2000-01-02 16:00:00', '2000-01-02 20:00:00',\n",
       "               '2000-01-03 00:00:00', '2000-01-03 04:00:00',\n",
       "               '2000-01-03 08:00:00', '2000-01-03 12:00:00',\n",
       "               '2000-01-03 16:00:00', '2000-01-03 20:00:00'],\n",
       "              dtype='datetime64[ns]', freq='4H')"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.date_range('2000-01-01', '2000-01-03 23:59', freq='4H')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "很多偏移(offset)还能和加法结合："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<150 * Minutes>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Hour(2) + Minute(30)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "同样的，我们可以传入频度字符串，比如'1h30min'，这种表达也能被解析："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 01:30:00',\n",
       "               '2000-01-01 03:00:00', '2000-01-01 04:30:00',\n",
       "               '2000-01-01 06:00:00', '2000-01-01 07:30:00',\n",
       "               '2000-01-01 09:00:00', '2000-01-01 10:30:00',\n",
       "               '2000-01-01 12:00:00', '2000-01-01 13:30:00'],\n",
       "              dtype='datetime64[ns]', freq='90T')"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.date_range('2000-01-01', periods=10, freq='1h30min')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Week of month dates（月中的第几周日期）\n",
    "\n",
    "一个有用的类（class）是月中的第几周（Week of month），用WOM表示。丽日我们想得到每个月的第三个星期五：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2012-01-20', '2012-02-17', '2012-03-16', '2012-04-20',\n",
       "               '2012-05-18', '2012-06-15', '2012-07-20', '2012-08-17'],\n",
       "              dtype='datetime64[ns]', freq='WOM-3FRI')"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rng = pd.date_range('2012-01-01', '2012-09-01', freq='WOM-3FRI')\n",
    "rng"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Timestamp('2012-01-20 00:00:00', offset='WOM-3FRI'),\n",
       " Timestamp('2012-02-17 00:00:00', offset='WOM-3FRI'),\n",
       " Timestamp('2012-03-16 00:00:00', offset='WOM-3FRI'),\n",
       " Timestamp('2012-04-20 00:00:00', offset='WOM-3FRI'),\n",
       " Timestamp('2012-05-18 00:00:00', offset='WOM-3FRI'),\n",
       " Timestamp('2012-06-15 00:00:00', offset='WOM-3FRI'),\n",
       " Timestamp('2012-07-20 00:00:00', offset='WOM-3FRI'),\n",
       " Timestamp('2012-08-17 00:00:00', offset='WOM-3FRI')]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(rng)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3 Shifting (Leading and Lagging) Data （偏移（提前与推后）数据）\n",
    "\n",
    "偏移（shifting）表示按照时间把数据向前或向后推移。Series和DataFrame都有一个shift方法实现偏移，索引（index）不会被更改："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31   -0.050276\n",
       "2000-02-29    0.080201\n",
       "2000-03-31    1.548324\n",
       "2000-04-30    0.510664\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts = pd.Series(np.random.randn(4),\n",
    "               index=pd.date_range('1/1/2000', periods=4, freq='M'))\n",
    "ts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31         NaN\n",
       "2000-02-29         NaN\n",
       "2000-03-31   -0.050276\n",
       "2000-04-30    0.080201\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts.shift(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31    1.548324\n",
       "2000-02-29    0.510664\n",
       "2000-03-31         NaN\n",
       "2000-04-30         NaN\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts.shift(-2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当我们进行位移的时候，就像上面这样会引入缺失值。\n",
    "\n",
    "shift的一个普通的用法是计算时间序列的百分比变化，可以表示为："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31          NaN\n",
       "2000-02-29    -2.595227\n",
       "2000-03-31    18.305554\n",
       "2000-04-30    -0.670183\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts / ts.shift(1) - 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "因为普通的shift不会对index进行修改，一些数据会被丢弃。因此如果频度是已知的，可以把频度传递给shift，这样的话时间戳会自动变化："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31   -0.050276\n",
       "2000-02-29    0.080201\n",
       "2000-03-31    1.548324\n",
       "2000-04-30    0.510664\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31         NaN\n",
       "2000-02-29         NaN\n",
       "2000-03-31   -0.050276\n",
       "2000-04-30    0.080201\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts.shift(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-03-31   -0.050276\n",
       "2000-04-30    0.080201\n",
       "2000-05-31    1.548324\n",
       "2000-06-30    0.510664\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts.shift(2, freq='M')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其他一些频度也可以导入，能让我们前后移动数据："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-02-03   -0.050276\n",
       "2000-03-03    0.080201\n",
       "2000-04-03    1.548324\n",
       "2000-05-03    0.510664\n",
       "dtype: float64"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts.shift(3, freq='D')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31 01:30:00   -0.050276\n",
       "2000-02-29 01:30:00    0.080201\n",
       "2000-03-31 01:30:00    1.548324\n",
       "2000-04-30 01:30:00    0.510664\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts.shift(1, freq='90T')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "T表示分钟。\n",
    "\n",
    "\n",
    "### Shifting dates with offsets（用偏移量来移动日期）\n",
    "\n",
    "pandas的日期偏移（date offset）能被用于datetime或Timestamp对象："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pandas.tseries.offsets import Day, MonthEnd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "now = datetime(2011, 11, 17)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2011-11-20 00:00:00')"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "now + 3 * Day()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果我们添加一个像MonthEnd这样的anchored offset(依附偏移；锚点位置)，日期会根据频度规则进行递增："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2011-11-30 00:00:00')"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "now + MonthEnd()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2011-12-31 00:00:00')"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "now + MonthEnd(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "依附偏移可以让日期向前或向后滚动，利用rollforward和rollback方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "offset = MonthEnd()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2011-11-30 00:00:00')"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "offset.rollforward(now)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2011-10-31 00:00:00')"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "offset.rollback(now)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "一个比较创造性的日期偏移（date offset）用法是配合groupby一起用："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-15    0.362927\n",
       "2000-01-19   -1.107020\n",
       "2000-01-23   -0.629370\n",
       "2000-01-27   -0.730651\n",
       "2000-01-31    0.251607\n",
       "2000-02-04    0.002611\n",
       "2000-02-08   -0.049611\n",
       "2000-02-12   -0.170408\n",
       "2000-02-16   -1.512385\n",
       "2000-02-20    1.335117\n",
       "2000-02-24   -0.393943\n",
       "2000-02-28    0.087478\n",
       "2000-03-03    0.441593\n",
       "2000-03-07   -0.940983\n",
       "2000-03-11   -1.399163\n",
       "2000-03-15    0.901478\n",
       "2000-03-19    0.392408\n",
       "2000-03-23   -0.512613\n",
       "2000-03-27    0.026952\n",
       "2000-03-31    1.200684\n",
       "Freq: 4D, dtype: float64"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts = pd.Series(np.random.randn(20),\n",
    "               index=pd.date_range('1/15/2000', periods=20, freq='4d'))\n",
    "ts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31   -0.370501\n",
       "2000-02-29   -0.100163\n",
       "2000-03-31    0.013794\n",
       "dtype: float64"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts.groupby(offset.rollforward).mean()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "一个简单且快捷的方式是用resample(11.6会进行更详细的介绍)："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000-01-31   -0.370501\n",
       "2000-02-29   -0.100163\n",
       "2000-03-31    0.013794\n",
       "Freq: M, dtype: float64"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ts.resample('M').mean()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [py35]",
   "language": "python",
   "name": "Python [py35]"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
